package com.uinnova.product.eam.service.dmv.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.binary.core.util.BinaryUtils;
import com.binary.jdbc.Page;
import com.uinnova.product.eam.comm.exception.BusinessException;
import com.uinnova.product.eam.comm.model.CVcBaseConfig;
import com.uinnova.product.eam.comm.model.VcBaseConfig;
import com.uinnova.product.eam.comm.model.es.EamDiagramRelationSys;
import com.uinnova.product.eam.model.VcCiClassInfo;
import com.uinnova.product.eam.model.VcCiRltInfo;
import com.uinnova.product.eam.model.constants.DmvConstants;
import com.uinnova.product.eam.model.dmv.*;
import com.uinnova.product.eam.model.dto.DmvAppWallCardDto;
import com.uinnova.product.eam.model.dto.DmvAppWallDto;
import com.uinnova.product.eam.model.dto.DmvAppWallFieldDto;
import com.uinnova.product.eam.service.BaseConfigService;
import com.uinnova.product.eam.service.EamDiagramRelationSysService;
import com.uinnova.product.eam.service.ICIRltSwitchSvc;
import com.uinnova.product.eam.service.ICISwitchSvc;
import com.uinnova.product.eam.service.dmv.DmvAppWallService;
import com.uinnova.product.eam.service.es.BaseConfigDao;
import com.uinnova.product.eam.service.utils.IntegrationHelper;
import com.uinnova.product.vmdb.comm.i18n.MessageUtil;
import com.uinnova.product.vmdb.comm.model.ci.CCcCi;
import com.uinnova.product.vmdb.comm.model.ci.CCcCiClass;
import com.uinnova.product.vmdb.comm.model.ci.CcCi;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiClassInfo;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiInfo;
import com.uinnova.product.vmdb.provider.rlt.bean.CcCiRltInfo;
import com.uinnova.project.api.diagram.v2.client.ESDiagramApiClient;
import com.uinnova.project.base.diagram.comm.model.*;
import com.uino.api.client.cmdb.IRltClassApiSvc;
import com.uino.bean.cmdb.base.ESCIAttrDefInfo;
import com.uino.bean.cmdb.base.ESCIClassInfo;
import com.uino.bean.cmdb.base.ESCIInfo;
import com.uino.bean.cmdb.base.LibType;
import com.uino.bean.cmdb.query.ESRltSearchBean;
import com.uino.bean.permission.base.SysUser;
import com.uino.service.cmdb.microservice.ICIClassSvc;
import com.uino.util.sys.SysUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description: 全景应用墙
 * @author: Lc
 * @create: 2022-04-19 10:51
 */
@Service
public class DmvAppWallServiceImpl implements DmvAppWallService {

    private static final Integer DIR_TYPE = 11;

    @Value("${http.resource.space}")
    private String httpResouceUrl;

    @Resource
    private ICISwitchSvc iciSwitchSvc;

    @Resource
    private BaseConfigService baseConfigService;

    @Resource
    private ICIRltSwitchSvc iciRltSwitchSvc;

    @Resource
    private IRltClassApiSvc iRltClassApiSvc;

    @Resource
    private ESDiagramApiClient diagramApiClient;

    @Resource
    private ICIClassSvc iciClassSvc;

    @Resource
    private BaseConfigDao baseConfigDao;

    @Resource
    private EamDiagramRelationSysService eamDiagramRelationSysService;

    @Override
    public List<CiInfoResponse> findAppWallList(SysUser sysUser) {
        // 校验参数，并获取classId
        JSONObject appWallJson = checkParam(DmvConstants.APP_WALL_CONFIG);
        Long classId = appWallJson.getLong(DmvConstants.APP_CLASS);

        // 查询属性定义
        ESCIClassInfo esciClassInfo = iciClassSvc.queryESClassInfoById(classId);
        if (esciClassInfo == null || CollectionUtils.isEmpty(esciClassInfo.getAttrDefs())) {
            throw new BusinessException("获取属性定义出错!");
        }

        // 获取需要隐藏的数据
        String hideAttrList = appWallJson.getString("hideAttrList");
        JSONArray jsonArray = null;
        if (!StringUtils.isEmpty(hideAttrList)) {
            jsonArray = JSONObject.parseArray(hideAttrList);
        }

        CCcCi cdt = new CCcCi();
        cdt.setClassId(classId);
        List<CcCiInfo> ccCiInfoList = iciSwitchSvc.queryCiInfoList(sysUser.getDomainId(), cdt, null, false, false, LibType.DESIGN);
        List<CiInfoResponse> ciList = new ArrayList<>(ccCiInfoList.size());
        for(int i = 0; i < ccCiInfoList.size(); i++) {
            CcCiInfo ccCiInfo = ccCiInfoList.get(i);
            CiInfoResponse ciInfo = new CiInfoResponse();
            BeanUtils.copyProperties(ccCiInfo, ciInfo);
            if (ccCiInfo.getAttrs() != null) {
                Map<String, String> attrs = ccCiInfo.getAttrs();
                boolean filter = false;
                if (jsonArray != null && jsonArray.size() > 0) {
                    for (int j = 0; j < jsonArray.size(); j++) {
                        JSONObject jsonObject = jsonArray.getJSONObject(j);
                        String key = jsonObject.getString("key");
                        String value = jsonObject.getString("value");
                        if (!StringUtils.isEmpty(key) && !StringUtils.isEmpty(value)) {
                            String content = attrs.get(key);
                            JSONArray valJSON = JSONObject.parseArray(value);
                            List<String> contentList = valJSON.toJavaList(String.class);
                            if (!StringUtils.isEmpty(content) && !CollectionUtils.isEmpty(contentList) && contentList.contains(content)) {
                                filter = true;
                                break;
                            }
                        }
                    }
                }
                // 过滤
                if (filter) {
                    continue;
                }

                // 实现属性的顺序
                List<AttrInfo> attrInfoList = findAttrInfoList(esciClassInfo, attrs);
                ciInfo.setAttrInfoList(attrInfoList);
            }
            ciList.add(ciInfo);
        }
        orderAppWallByResults(ciList, sysUser.getDomainId(), classId);
        return ciList;
    }

    @Override
    public List<VcCiRltInfo> queryCiBetweenRlt(Long[] ciIds, String[] ciCodes, Long[] classIds, Integer[] types, VcCiRltQ[] ciRltQs) {
        Long domainId = SysUtil.getCurrentUserInfo().getDomainId();
        if (BinaryUtils.isEmpty(ciIds)) {
            Set<Long> ciIdSet = new HashSet<Long>();
            MessageUtil.checkEmpty(ciCodes, "ciCodes");
            CCcCi cdt = new CCcCi();
            cdt.setCiCodes(ciCodes);
            CCcCi cCcCi = new CCcCi();
            cCcCi.setCiCodes(ciCodes);
            List<CcCi> ciList = iciSwitchSvc.queryCiList(domainId, cCcCi, null, false, LibType.DESIGN);

            ciList.forEach(ci -> {
                ciIdSet.add(ci.getId());
            });
            ciIds = ciIdSet.toArray(new Long[0]);
        }
        List<Long> ciIdList = asListFilterNull(ciIds);
        List<Long> rltClsIdList = asListFilterNull(classIds);
        MessageUtil.checkEmpty(ciIdList, "ciIds");
         return queryCiBetweenRlt(domainId, ciIdList, rltClsIdList, ciRltQs);
    }

    @Override
    public List<VcDiagramInfo> findAppDiagramList(String esSysId, Integer type) {
        if (esSysId == null) {
            throw new BusinessException("应用信息不能为空!");
        }
       /* List<EamDiagramDir> dirList = iDiagramDirSvc.findPublishedDirList(DIR_TYPE, esSysId);
        if (CollectionUtils.isEmpty(dirList)) {
            return null;
        }
        Set<Long> dirSet = dirList.stream().map(EamDiagramDir::getId).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(dirSet)) {
            return null;
        }
        List<Integer> dirTypeList = Stream.of(DIR_TYPE).collect(Collectors.toList());
        List<Integer> isOpenList = Stream.of(1).collect(Collectors.toList());
        List<ESDiagram> esDiagramList = diagramApiClient.selectByDirIds(dirSet, dirTypeList, null, isOpenList);
        if (CollectionUtils.isEmpty(esDiagramList)) {
            return null;
        }*/
        List<EamDiagramRelationSys> diagramRelationSysList = eamDiagramRelationSysService.findDiagramRelationSysList(esSysId);
        if (CollectionUtils.isEmpty(diagramRelationSysList)) {
            return Collections.emptyList();
        }
        Set<String> diagramEnergyIds = diagramRelationSysList.stream().filter(eamDiagramRelationSys -> !StringUtils.isEmpty(eamDiagramRelationSys.getDiagramEnergy()))
                .map(eamDiagramRelationSys -> eamDiagramRelationSys.getDiagramEnergy()).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(diagramEnergyIds)) {
            return Collections.emptyList();
        }
        List<ESDiagram> designEsDiagramsList = diagramApiClient.selectByIds(diagramEnergyIds, null, null);
        if (CollectionUtils.isEmpty(designEsDiagramsList)) {
            return Collections.emptyList();
        }
        Set<String> releaseDiagramIds = designEsDiagramsList.stream().filter(esDiagram -> !StringUtils.isEmpty(esDiagram.getReleaseDiagramId()))
                .map(esDiagram -> esDiagram.getReleaseDiagramId()).collect(Collectors.toSet());
        List<ESDiagram> assetsEsDiagramsList = diagramApiClient. selectByIds(releaseDiagramIds, null, null);
        if (CollectionUtils.isEmpty(assetsEsDiagramsList)) {
            return Collections.emptyList();
        }
        Long[] ids = assetsEsDiagramsList.stream().map(ESDiagram::getId).toArray(Long[]::new);
        if (ids == null || ids.length <= 0) {
            return Collections.emptyList();
        }
        List<ESDiagramDTO> esDiagramDTOS = diagramApiClient.queryDiagramInfoByIds(ids, null, false, false);
        if (CollectionUtils.isEmpty(esDiagramDTOS)) {
            return Collections.emptyList();
        }
        List<ESDiagramDTO> esDiagramDTOList = esDiagramDTOS.stream().filter(esDiagram -> !StringUtils.isEmpty(esDiagram.getDiagram().getReleaseDiagramId())).collect(Collectors.toList());
        Collections.sort(esDiagramDTOList, (o1, o2) -> {
            return (int)(o1.getDiagram().getModifyTime() - o2.getDiagram().getModifyTime());
        });

        CVcBaseConfig wallCdt = new CVcBaseConfig();
        if (Objects.equals(DmvConstants.DOMAIN_SET_CONFIG_DIAGRAM, type)) {
            wallCdt.setCfgCode(DmvConstants.DOMAIN_SET_CONFIG);
        } else {
            wallCdt.setCfgCode(DmvConstants.APP_WALL_CONFIG);
        }
        List<VcBaseConfig> vcBaseConfigs = baseConfigService.queryBaseConfigList(wallCdt);
        if (CollectionUtils.isEmpty(vcBaseConfigs)) {
            throw new BusinessException("获取全景墙配置出错!");
        }
        VcBaseConfig vcBaseConfig = vcBaseConfigs.get(0);
        String cfgContent = vcBaseConfig.getCfgContent();
        if (StringUtils.isEmpty(cfgContent)) {
            throw new BusinessException("获取全景墙配置出错!");
        }
        JSONObject appWallJson = JSONObject.parseObject(cfgContent);
        JSONArray jsonArr = appWallJson.getJSONArray("viewType");
        List<String> viewTypeList = jsonArr.toJavaList(String.class);
        if (CollectionUtils.isEmpty(viewTypeList)) {
            throw new BusinessException("未配置制品分类!");
        }

        Map<String, ESDiagramDTO> diagramMap = new HashMap<>();
        esDiagramDTOList.forEach(esDiagramDTO -> {
            String viewType = esDiagramDTO.getDiagram().getViewType();
            if (viewTypeList.contains(viewType)) {
                diagramMap.put(viewType, esDiagramDTO);
            }
        });

        //List<ESDiagramDTO> esDiagrams = diagramMap.entrySet().stream().sorted().map(item -> item.getValue()).collect(Collectors.toList());
        List<ESDiagramDTO> esDiagrams = new ArrayList<>();
        for (String viewType : viewTypeList) {
            ESDiagramDTO esDiagramDTO = diagramMap.get(viewType);
            if (esDiagramDTO == null) {
                continue;
            }
            esDiagrams.add(esDiagramDTO);
        }
        List<VcDiagramInfo> list = new ArrayList<>();
        if (!CollectionUtils.isEmpty(esDiagrams)) {
            esDiagrams.forEach(esDiagram -> {
                VcDiagramInfo vcDiagramInfo = new VcDiagramInfo();
                NodeAndEdges nodeAndEdges = new NodeAndEdges();
                if (esDiagram != null && !CollectionUtils.isEmpty(esDiagram.getDiagram().getModelList())) {
                    ESDiagramModel esDiagramModel = esDiagram.getDiagram().getModelList().get(0);
                    if (esDiagramModel != null) {
                        // 线
                        List<ESDiagramLink> linkDataArray = esDiagramModel.getLinkDataArray();
                        // 目标端（包含的对象）
                        List<String> toList = new ArrayList<>();
                        // 源端（被包含的对象）
                        List<String> fromList = new ArrayList<>();
                        if (!CollectionUtils.isEmpty(linkDataArray)) {
                            List<DiagramLink> linkListInfo = new ArrayList<>();
                            for(int link = 0; link < linkDataArray.size(); link++) {
                                ESDiagramLink linkArray = linkDataArray.get(link);
                                if (linkArray == null || StringUtils.isEmpty(linkArray.getLinkJson())) {
                                    continue;
                                }
                                JSONObject linkJson = JSONObject.parseObject(linkArray.getLinkJson());
                                String createMode = linkJson.getString("createMode");
                                if (!StringUtils.isEmpty(createMode)) {
                                    toList.add(linkJson.getString("to"));
                                    fromList.add(linkJson.getString("from"));
                                    continue;
                                }
                                DiagramLink diagramLink = new DiagramLink();
                                diagramLink.setId(linkJson.getString("key"));
                                diagramLink.setStrokeWidth(linkJson.getInteger("strokeWidth"));
                                diagramLink.setText(linkJson.getString("label"));
                                diagramLink.setSourceId(linkJson.getString("from"));
                                diagramLink.setTargetId(linkJson.getString("to"));
                                diagramLink.setZOrder(linkJson.getInteger("zOrder"));
                                String linkPoints = linkJson.getString("points");
                                JSONArray points = new JSONArray();
                                if (linkPoints.contains("x") && linkPoints.contains("y")) {
                                    // 兼容\"points\":[{\"v\":true,\"x\":-411,\"y\":359}]格式数据
                                    JSONArray pointArr = linkJson.getJSONArray("points");
                                    for (int i = 0; i < pointArr.size(); i++) {
                                        JSONObject jsonObject = JSONObject.parseObject(pointArr.getString(i));
                                        points.add(jsonObject.getString("x"));
                                        points.add(jsonObject.getString("y"));
                                    }
                                } else {
                                    // 兼容\"points\":[-780,369,-617,369,-617,309,-454,309]格式数据
                                    points = linkJson.getJSONArray("points");
                                }
                                List<DiagramLinkLoc> linkLocList  = new ArrayList<>();
                                if (points != null) {
                                    for (int i = 0; i < points.size(); i++) {
                                        if (i % 2 != 0) {
                                            continue;
                                        }
                                        DiagramLinkLoc diagramLinkLoc = new DiagramLinkLoc();
                                        diagramLinkLoc.setX(Double.valueOf(points.get(i).toString()));
                                        diagramLinkLoc.setY(Double.valueOf(points.get(i + 1).toString()));
                                        linkLocList.add(diagramLinkLoc);
                                    }
                                    diagramLink.setPoints(linkLocList);
                                }
                                linkListInfo.add(diagramLink);
                            }
                            nodeAndEdges.setEdges(linkListInfo);
                        }

                        // 节点
                        List<ESDiagramNode> nodeDataArray = esDiagramModel.getNodeDataArray();
                        if (!CollectionUtils.isEmpty(nodeDataArray)) {
                            List<DiagramNode> nodeListInfo = new ArrayList<>();
                            nodeDataArray.forEach(nodeArray -> {
                                JSONObject nodeJson = JSONObject.parseObject(nodeArray.getNodeJson());
                                DiagramNode diagramNode = new DiagramNode();
                                String key = nodeJson.getString("key");
                                if (!StringUtils.isEmpty(key)) {
                                    if (!CollectionUtils.isEmpty(toList) && toList.contains(key)) {
                                        diagramNode.setSign(DmvConstants.INCLUDED_OBJ);
                                    }
                                    if (!CollectionUtils.isEmpty(fromList) && fromList.contains(key)) {
                                        diagramNode.setSign(DmvConstants.INCLUDE_OBJ);
                                    }
                                }
                                diagramNode.setHeight(nodeJson.getInteger("height"));
                                diagramNode.setWidth(nodeJson.getInteger("width"));
                                if (!StringUtils.isEmpty(nodeJson.getString("loc"))) {
                                    String[] split = nodeJson.getString("loc").split(" ");
                                    diagramNode.setX(new BigDecimal(split[0]).doubleValue());
                                    diagramNode.setY(new BigDecimal(split[1]).doubleValue());
                                }
                                diagramNode.setImg(nodeJson.getString("shapeName"));
                                diagramNode.setName(nodeJson.getString("label"));
                                diagramNode.setZOrder(nodeJson.getInteger("zOrder"));
                                diagramNode.setId(key);
                                diagramNode.setImage(nodeJson.getString("image"));
                                diagramNode.setCiId(nodeJson.getLong("ciId"));
                                diagramNode.setCiCode(nodeJson.getString("ciCode"));
                                diagramNode.setClassId(nodeJson.getLong("classId"));
                                diagramNode.setClassName(nodeJson.getString("className"));
                                nodeListInfo.add(diagramNode);
                            });
                            nodeAndEdges.setNodes(nodeListInfo);
                        }
                    }
                    vcDiagramInfo.setDiagram(esDiagram.getDiagram());
                    vcDiagramInfo.setCi3dPoint(JSONObject.toJSONString(nodeAndEdges));
                    list.add(vcDiagramInfo);
                }
            });
        }
        return list;
    }

    @Override
    public Long saveAppSortConfig(VcBaseConfig record) {
        if (record == null) {
            throw new BusinessException("配置信息不能为空!");
        }
        JSONObject appWallJson = checkParam(DmvConstants.APP_WALL_CONFIG);
        Long classId = appWallJson.getLong(DmvConstants.APP_CLASS);

        CVcBaseConfig wallCdt = new CVcBaseConfig();
        wallCdt.setCfgCode(String.valueOf(classId));
        List<VcBaseConfig> vcBaseConfigs = baseConfigService.queryBaseConfigList(wallCdt);
        Long result = null;
        if (!CollectionUtils.isEmpty(vcBaseConfigs)) {
            VcBaseConfig vcBaseConfig = vcBaseConfigs.get(0);
            vcBaseConfig.setCfgContent(record.getCfgContent());
            result = baseConfigService.saveOrUpdateBaseConfig(vcBaseConfig);
        } else {
            record.setCfgCode(String.valueOf(classId));
            result = baseConfigService.saveOrUpdateBaseConfig(record);
        }
        return result;
    }

    @Override
    public List<Layer> findLayerDomainCiList(SysUser sysUser) {
        // 校验层域配置
        JSONObject appWallJson = checkParam(DmvConstants.DOMAIN_SET_CONFIG);
        Long classId = appWallJson.getLong(DmvConstants.APP_CLASS);

        JSONObject layerJson = appWallJson.getJSONObject(DmvConstants.LAYER_RELATION);
        if (layerJson == null || StringUtils.isEmpty(layerJson.getString(DmvConstants.NAME))) {
            throw new BusinessException("请配置层关联属性!");
        }

        JSONObject fieldJson = appWallJson.getJSONObject(DmvConstants.FIELD_RELATION);
        if (fieldJson == null || StringUtils.isEmpty(fieldJson.getString(DmvConstants.NAME))) {
            throw new BusinessException("请配置域关联属性!");
        }
        // 查询属性定义
        ESCIClassInfo esciClassInfo = iciClassSvc.queryESClassInfoById(classId);
        if (esciClassInfo == null || CollectionUtils.isEmpty(esciClassInfo.getAttrDefs())) {
            throw new BusinessException("获取属性定义出错!");
        }

        // 获取需要隐藏的数据
        String hideAttrList = appWallJson.getString("hideAttrList");
        JSONArray jsonArray = null;
        if (!StringUtils.isEmpty(hideAttrList)) {
            jsonArray = JSONObject.parseArray(hideAttrList);
        }

        CCcCi cdt = new CCcCi();
        cdt.setClassId(classId);
        List<CcCiInfo> ccCiInfoList = iciSwitchSvc.queryCiInfoList(sysUser.getDomainId(), cdt, null, false, false, LibType.DESIGN);
        Map<String, Map<String, List<CiInfoResponse>>> map = new LinkedHashMap<>();
        for(int i = 0; i < ccCiInfoList.size(); i++) {
            CcCiInfo ciInfo = ccCiInfoList.get(i);
            Map<String, String> attrs = ciInfo.getAttrs();
            boolean filter = false;
            if (jsonArray != null && jsonArray.size() > 0) {
                for (int j = 0; j < jsonArray.size(); j++) {
                    JSONObject jsonObject = jsonArray.getJSONObject(j);
                    String key = jsonObject.getString("key");
                    String value = jsonObject.getString("value");
                    if (!StringUtils.isEmpty(key) && !StringUtils.isEmpty(value)) {
                        String content = attrs.get(key);
                        JSONArray valJSON = JSONObject.parseArray(value);
                        List<String> contentList = valJSON.toJavaList(String.class);
                        if (!StringUtils.isEmpty(content) && !CollectionUtils.isEmpty(contentList) && contentList.contains(content)) {
                            filter = true;
                            break;
                        }
                    }
                }
            }

            // 过滤
            if (filter) {
                continue;
            }

            String layer = attrs.get(layerJson.getString(DmvConstants.NAME));
            if (StringUtils.isEmpty(layer)) {
                continue;
            }
            String domain = !StringUtils.isEmpty(attrs.get(fieldJson.getString(DmvConstants.NAME))) ? attrs.get(fieldJson.getString(DmvConstants.NAME)) : "0";

            List<CiInfoResponse> ciList = null;
            Map<String, List<CiInfoResponse>> domainMap = null;
            if (map.get(layer) != null) {
                domainMap = map.get(layer);
                ciList = domainMap.get(domain);
                if (CollectionUtils.isEmpty(ciList)) {
                    ciList = new ArrayList<>();
                }
            } else {
                domainMap = new LinkedHashMap<>();
                ciList = new ArrayList<>();
            }

            CiInfoResponse response = new CiInfoResponse();
            BeanUtils.copyProperties(ciInfo, response);
            // 实现属性的顺序
            List<AttrInfo> attrInfoList = findAttrInfoList(esciClassInfo, attrs);
            response.setAttrInfoList(attrInfoList);
            ciList.add(response);
            // 存到域map中
            domainMap.put(domain, ciList);
            // 存到层map中
            map.put(layer, domainMap);
        }

        if (map.size() > 0) {
            // 获取层、域、应用配置
            List<String> layerDomainConfigs = new ArrayList<>();
            layerDomainConfigs.add(DmvConstants.LAYER_CONFIG);
            layerDomainConfigs.add(DmvConstants.LAYER_DOMAIN_CONFIG);
            layerDomainConfigs.add(DmvConstants.LAYER_DOMAIN_APP_CONFIG);
            List<VcBaseConfig> baseConfigList = baseConfigService.findBaseConfigList(layerDomainConfigs);
            Map<String, VcBaseConfig> baseConfigMap = null;
            if (!CollectionUtils.isEmpty(baseConfigList)) {
                baseConfigMap = baseConfigList.stream().collect(Collectors.toMap(VcBaseConfig::getCfgCode, VcBaseConfig -> VcBaseConfig));
            }

            if (baseConfigMap != null && baseConfigMap.size() > 0) {
                Map<String, Map<String, List<CiInfoResponse>>> newMap = map;
                VcBaseConfig layerConfig = baseConfigMap.get(DmvConstants.LAYER_CONFIG);
                if (layerConfig != null && !StringUtils.isEmpty(layerConfig.getCfgContent())) {
                    // 清空map重新排序
                    map = new LinkedHashMap<>();
                    String[] layers = layerConfig.getCfgContent().split(",");
                    for (String layer : layers) {
                        if (newMap.get(layer) != null) {
                            map.put(layer, newMap.get(layer));
                        }
                    }
                    if (newMap.size() != map.size()) {
                        map.clear();
                        map.putAll(newMap);
                    }
                }

                // 层下的域重新排序
                VcBaseConfig layerDomainConfig = baseConfigMap.get(DmvConstants.LAYER_DOMAIN_CONFIG);
                if (layerDomainConfig != null && !StringUtils.isEmpty(layerDomainConfig.getCfgContent())) {
                    JSONObject jsonObject = JSONObject.parseObject(layerDomainConfig.getCfgContent());
                    String value = jsonObject.getString("value");
                    if (!StringUtils.isEmpty(jsonObject.getString("layer")) && !StringUtils.isEmpty(value) && value.split(",").length > 0) {
                        String[] split = value.split(",");
                        if (map.size() > 0 && map.size() == newMap.size()) {
                            Map<String, List<CiInfoResponse>> domainMap = map.get(jsonObject.getString("layer"));
                            if (domainMap != null && domainMap.size() > 0) {
                                Map<String, List<CiInfoResponse>> newDomainMap = domainMap;
                                domainMap = new LinkedHashMap<>();
                                for (String domain : split) {
                                    if (newDomainMap.get(domain) != null) {
                                        domainMap.put(domain, newDomainMap.get(domain));
                                    }
                                }
                                if (newDomainMap.get("0") != null && newDomainMap.get("0").size() > 0) {
                                    domainMap.put("0", newDomainMap.get("0"));
                                }
                                if (newDomainMap.size() != domainMap.size()) {
                                    domainMap.clear();
                                    domainMap.putAll(newDomainMap);
                                }
                                map.put(jsonObject.getString("layer"), domainMap);
                            }
                        }
                    }
                }

                // 层或域下的应用重新排序
                VcBaseConfig layerDomainAppConfig = baseConfigMap.get(DmvConstants.LAYER_DOMAIN_APP_CONFIG);
                if (layerDomainAppConfig != null && !StringUtils.isEmpty(layerDomainAppConfig.getCfgContent())) {
                    JSONObject jsonObject = JSONObject.parseObject(layerDomainAppConfig.getCfgContent());
                    String layer = jsonObject.getString("layer");
                    String domain = jsonObject.getString("domain");
                    String value = jsonObject.getString("value");
                    if (!StringUtils.isEmpty(layer) && !StringUtils.isEmpty(domain) && !StringUtils.isEmpty(value) && value.split(",").length > 0) {
                        String[] split = value.split(",");
                        Map<String, List<CiInfoResponse>> domainMap = map.get(layer);
                        if (domainMap != null && domainMap.size() > 0) {
                            List<CiInfoResponse> dataList = domainMap.get(domain);
                            if (!CollectionUtils.isEmpty(dataList)) {
                                Map<String, CiInfoResponse> ciInfoMap = new HashMap<>();
                                for (CiInfoResponse ci : dataList) {
                                    ciInfoMap.put(ci.getCi().getCiCode(), ci);
                                }
                                List<CiInfoResponse> newDataList = new ArrayList<>();
                                for (String data : split) {
                                    newDataList.add(ciInfoMap.get(data));
                                }
                                if (newDataList.size() == dataList.size()) {
                                    domainMap.put(domain, newDataList);
                                }
                            }
                        }
                    }
                }
            }
        }

        List<Layer> list = new ArrayList<>();
        if (map.size() > 0) {
            for (Map.Entry<String, Map<String, List<CiInfoResponse>>> mapEntry : map.entrySet()) {
                String layerKey = mapEntry.getKey();
                Map<String, List<CiInfoResponse>> domainMap = mapEntry.getValue();
                Layer layer = new Layer();
                List<Domain> domainList = new ArrayList<>();
                layer.setLayerName(layerKey);
                for (Map.Entry<String, List<CiInfoResponse>> domainEntry : domainMap.entrySet()) {
                    String domainKey = domainEntry.getKey();
                    List<CiInfoResponse> ciInfo = domainEntry.getValue();
                    Domain domain = new Domain();
                    domain.setDomainName(domainKey);
                    domain.setCiInfoResponseList(ciInfo);
                    domainList.add(domain);
                }
                layer.setDomainList(domainList);
                list.add(layer);
            }
        }

        return list;

    }

    @Override
    public Object getCardInfos(String ciCode, String cfgCode) {
        List<ESCIInfo> ciInfos = iciSwitchSvc.getCiByCodes(Collections.singletonList(ciCode), null, LibType.DESIGN);
        if (ciInfos == null || ciInfos.size() < 1) {
            throw new BusinessException("查询的ci信息有误");
        }
        ESCIInfo esciInfo = ciInfos.get(0);
        CVcBaseConfig cVcBaseConfig = new CVcBaseConfig();
        cVcBaseConfig.setCfgCode(cfgCode);
        List<VcBaseConfig> baseList = baseConfigDao.getListByCdt(cVcBaseConfig);
        if (baseList == null || baseList.size() < 1) {
            throw new BusinessException("获取全景墙配置信息有误");
        }
        VcBaseConfig vcBaseConfig = baseList.get(0);
        String cfgContent = vcBaseConfig.getCfgContent();
        JSONObject jsonObject = JSONObject.parseObject(cfgContent);
        JSONArray appAttrArray = jsonObject.getJSONArray("tagAssociationInfoConfig");
        if (appAttrArray == null || appAttrArray.size() < 1) {
            throw new BusinessException("配置信息没有配置走原来的逻辑");
        }
        List<DmvAppWallDto> dmvAppWallDtoList =  JSON.parseObject(appAttrArray.toJSONString(),new TypeReference<List<DmvAppWallDto>>(){});
        List<DmvAppWallCardDto> result = new ArrayList<>();
        for (DmvAppWallDto dmvAppWallDto : dmvAppWallDtoList) {
            DmvAppWallCardDto dmvAppWallCardDto = new DmvAppWallCardDto();
            List<DmvAppWallFieldDto> infos = new ArrayList<>();
            if (dmvAppWallDto.getAssociationInfo() == null || dmvAppWallDto.getAssociationInfo().length < 1) {
                continue;
            }
            for (String key : dmvAppWallDto.getAssociationInfo()) {
                if (BeanUtil.isNotEmpty(esciInfo.getAttrs().get(key))) {
                    DmvAppWallFieldDto dmvAppWallFieldDto = new DmvAppWallFieldDto();
                    dmvAppWallFieldDto.setInfoKey(key);
                    dmvAppWallFieldDto.setInfoValue(esciInfo.getAttrs().get(key).toString());
                    infos.add(dmvAppWallFieldDto);
                }else{
                    DmvAppWallFieldDto dmvAppWallFieldDto = new DmvAppWallFieldDto();
                    dmvAppWallFieldDto.setInfoKey(key);
                    dmvAppWallFieldDto.setInfoValue("");
                    infos.add(dmvAppWallFieldDto);
                }
            }
            dmvAppWallCardDto.setLabelName(dmvAppWallDto.getTagName());
            dmvAppWallCardDto.setInfos(infos);
            result.add(dmvAppWallCardDto);
        }
        return  result;
    }

    private List<AttrInfo> findAttrInfoList(ESCIClassInfo esciClassInfo, Map<String, String> attrs) {
        List<AttrInfo> attrInfoList = new ArrayList<>();
        List<ESCIAttrDefInfo> attrDefs = esciClassInfo.getAttrDefs();
        for (int j = 0; j < attrDefs.size(); j++) {
            String proName = attrDefs.get(j).getProName();
            AttrInfo attrInfo = new AttrInfo();
            attrInfo.setKey(proName);
            attrInfo.setValue(attrs.get(proName));
            attrInfoList.add(attrInfo);
        }
        return attrInfoList;
    }

    private <T> List<T> asListFilterNull(T[] r) {
        if (r == null) { return Collections.emptyList(); }
        List<T> tm = new ArrayList<T>();
        for (T t : r) {
            if (t != null) {
                tm.add(t);
            }
        }
        return tm;
    }

    private List<VcCiRltInfo> queryCiBetweenRlt(Long domainId, List<Long> ciIds, List<Long> classIds, VcCiRltQ[] ciRltQs) {
        BinaryUtils.checkEmpty(ciIds, "ciIds");
        ESRltSearchBean cdt = new ESRltSearchBean();
        cdt.setPageNum(1);
        cdt.setPageSize(10000);
        cdt.setDomainId(domainId);
        cdt.setSourceCiIds(ciIds);
        cdt.setTargetCiIds(ciIds);
        if (classIds != null) {
            cdt.setRltClassIds(classIds);
        }
        Page<CcCiRltInfo> page = iciRltSwitchSvc.searchRltByBean(cdt,LibType.DESIGN);
        List<CcCiRltInfo> data = page.getData();
        List<VcCiRltInfo> rltInfos = IntegrationHelper.converCiRlt(data);
        Set<Long> clsIds = rltInfos.stream().map(rlt -> rlt.getCiRlt().getClassId()).collect(Collectors.toSet());
        if (!clsIds.isEmpty()) {
            CCcCiClass cCcCiClass = new CCcCiClass();
            cCcCiClass.setIds(clsIds.toArray(new Long[clsIds.size()]));
            Map<Long, CcCiClassInfo> idMap = iRltClassApiSvc.getRltClassByCdt(cCcCiClass).stream().collect(Collectors.toMap(c -> c.getCiClass().getId(), a -> a,(k1,k2) -> k2));

            rltInfos.forEach(info -> {
                CcCiClassInfo ccCiClassInfo = idMap.get(info.getCiRlt().getClassId());
                VcCiClassInfo vcCiClassInfo = new VcCiClassInfo();
                vcCiClassInfo.setCiClass(ccCiClassInfo.getCiClass());
                vcCiClassInfo.setAttrDefs(ccCiClassInfo.getAttrDefs());
                vcCiClassInfo.setCiCount(ccCiClassInfo.getCiCount());
                vcCiClassInfo.setFixMapping(ccCiClassInfo.getFixMapping());
                vcCiClassInfo.setFixMapping(ccCiClassInfo.getFixMapping());
                info.setRltClassInfo(vcCiClassInfo);
            });
        }
        return rltInfos;
    }

    private void orderAppWallByResults(List<CiInfoResponse> results, Long domainId, Long classId) {
        List<String> ciIds = null;
        CVcBaseConfig cdt = new CVcBaseConfig();
        cdt.setCfgCode(String.valueOf(classId));
        cdt.setDomainId(domainId);
        List<VcBaseConfig> vcBaseConfigList = baseConfigService.queryBaseConfigList(cdt);
        if (CollectionUtils.isEmpty(vcBaseConfigList)) {
            return;
        }
        VcBaseConfig vcBaseConfig = vcBaseConfigList.get(0);
        if (vcBaseConfig == null) {
            return;
        }
        if (!StringUtils.isEmpty(vcBaseConfig.getCfgContent())) {
            String[] split = vcBaseConfig.getCfgContent().split(",");
            ciIds = Arrays.asList(split);
        }

        if (ciIds == null || ciIds.size() <= 0) {
            return;
        }
        /// 开始为原始结果赋予排序分数
        // 先组织结果id:obj map 方便寻找对象
        Map<String, CiInfoResponse> resultMap = new HashMap<>();
        for (CiInfoResponse ciInfo : results) {
            resultMap.put(String.valueOf(ciInfo.getCi().getId()), ciInfo);
        }
        // 开始给ci打分,配置排序数组大小就是得分的最高分
        int score = ciIds.size();
        for (String orderCiId : ciIds) {
            try {
                CiInfoResponse ciInfoResponse = resultMap.get(orderCiId);
                if (ciInfoResponse != null) {
                    ciInfoResponse.setOrderScore(score);
                }
            } catch (Exception e) {
                throw new BusinessException("应用墙排序配置错误，请检查配置");
            }
            score--;
        }

        Collections.sort(results, (o1, o2) -> {
            if (o1.getOrderScore().equals(o2.getOrderScore()))
                return 0;
            if (o1.getOrderScore() > o2.getOrderScore())
                return -1;
            return 1;
        });
    }

    private JSONObject checkParam(String cfgCode) {
        CVcBaseConfig wallCdt = new CVcBaseConfig();
        wallCdt.setCfgCode(cfgCode);
        List<VcBaseConfig> vcBaseConfigs = baseConfigService.queryBaseConfigList(wallCdt);
        if (CollectionUtils.isEmpty(vcBaseConfigs)) {
            throw new BusinessException("获取全景墙配置出错!");
        }
        VcBaseConfig vcBaseConfig = vcBaseConfigs.get(0);
        String cfgContent = vcBaseConfig.getCfgContent();
        if (StringUtils.isEmpty(cfgContent)) {
            throw new BusinessException("获取全景墙配置出错!");
        }
        JSONObject appWallJson = JSONObject.parseObject(cfgContent);
        Long classId = appWallJson.getLong("appClass");
        CcCiClassInfo ccCiClassInfo = iciClassSvc.queryClassInfoById(classId);
        if (ccCiClassInfo == null) {
            throw new BusinessException("获取系统分类错误!");
        }
        return appWallJson;
    }

}
